const http = require('http');
const fs = require('fs');
const path = require('path');

// Use formidable for multipart parsing. Install with: npm i formidable
let IncomingForm;
try {
  ({ IncomingForm } = require('formidable'));
} catch (err) {
  console.error('缺少依赖 formidable，请先执行: npm i formidable');
  process.exit(1);
}

const ROOT = __dirname;
const PUBLIC_DIR = path.join(ROOT, 'public');
const UPLOAD_DIR = path.join(ROOT, 'upload');

if (!fs.existsSync(PUBLIC_DIR)) fs.mkdirSync(PUBLIC_DIR, { recursive: true });
if (!fs.existsSync(UPLOAD_DIR)) fs.mkdirSync(UPLOAD_DIR, { recursive: true });

function send(res, status, headers, body) {
  res.writeHead(status, headers);
  res.end(body);
}

function serveIndex(res) {
  const file = path.join(PUBLIC_DIR, 'index.html');
  const html = fs.readFileSync(file, 'utf-8');
  send(res, 200, { 'Content-Type': 'text/html; charset=utf-8' }, html);
}

function serveList(res) {
  const files = fs
    .readdirSync(UPLOAD_DIR)
    .filter((f) => /\.(png|jpg|jpeg|gif|webp|bmp)$/i.test(f));

  const cards = files
    .map(
      (name) =>
        `<div class="card"><img src="/upload/${encodeURIComponent(
          name
        )}" alt="${name}" /><div class="name">${name}</div></div>`
    )
    .join('');

  const html = `<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>图片列表</title>
  <style>
    body{font-family:Segoe UI,Helvetica,Arial,"PingFang SC","Microsoft Yahei",sans-serif;background:#f7f8fa;margin:0;padding:24px}
    h1{font-size:20px;margin:0 0 16px}
    .grid{display:flex;flex-wrap:wrap;gap:16px}
    .card{background:#fff;border-radius:10px;box-shadow:0 2px 10px rgba(0,0,0,.06);padding:10px;width:280px}
    .card img{width:100%;height:160px;object-fit:cover;border-radius:6px}
    .name{margin-top:8px;color:#39495a;font-size:12px;word-break:break-all}
    a.btn{display:inline-block;margin-bottom:16px;background:#1e80ff;color:#fff;padding:8px 12px;border-radius:6px;text-decoration:none}
  </style>
  </head>
<body>
  <a class="btn" href="/">返回上传</a>
  <h1>已上传图片</h1>
  <div class="grid">${cards || '<div>暂无图片</div>'}</div>
</body>
</html>`;
  send(res, 200, { 'Content-Type': 'text/html; charset=utf-8' }, html);
}

function serveStaticUpload(req, res) {
  const filePath = path.join(UPLOAD_DIR, decodeURIComponent(req.url.replace('/upload/', '')));
  if (!filePath.startsWith(UPLOAD_DIR)) {
    send(res, 403, { 'Content-Type': 'text/plain; charset=utf-8' }, 'Forbidden');
    return true;
  }
  if (!fs.existsSync(filePath)) return false;
  const ext = path.extname(filePath).toLowerCase();
  const typeMap = {
    '.png': 'image/png',
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.gif': 'image/gif',
    '.webp': 'image/webp',
    '.bmp': 'image/bmp',
  };
  const stream = fs.createReadStream(filePath);
  res.writeHead(200, { 'Content-Type': typeMap[ext] || 'application/octet-stream' });
  stream.pipe(res);
  return true;
}

function handleUpload(req, res) {
  const form = new IncomingForm({ multiples: false, uploadDir: UPLOAD_DIR, keepExtensions: true });
  form.parse(req, (err, fields, files) => {
    if (err) {
      send(res, 500, { 'Content-Type': 'text/plain; charset=utf-8' }, '上传失败: ' + err.message);
      return;
    }
    const file = files.file || files.image || files.upload || files[Object.keys(files)[0]];
    const storedPath = file && (file.filepath || file.path);
    const finalName = file && path.basename(storedPath || '');
    const result = `<!doctype html><meta charset="utf-8" /><p>上传成功: ${finalName}</p><p><a href="/list">查看列表</a> | <a href="/">继续上传</a></p>`;
    send(res, 200, { 'Content-Type': 'text/html; charset=utf-8' }, result);
  });
}

const server = http.createServer((req, res) => {
  if (req.method === 'GET' && req.url === '/') {
    serveIndex(res);
    return;
  }
  if (req.method === 'GET' && req.url === '/list') {
    serveList(res);
    return;
  }
  if (req.method === 'GET' && req.url.startsWith('/upload/')) {
    if (!serveStaticUpload(req, res)) {
      send(res, 404, { 'Content-Type': 'text/plain; charset=utf-8' }, 'Not Found');
    }
    return;
  }
  if (req.method === 'POST' && req.url === '/upload') {
    handleUpload(req, res);
    return;
  }
  send(res, 404, { 'Content-Type': 'text/plain; charset=utf-8' }, 'Not Found');
});

const PORT = 8081;
server.listen(PORT, () => {
  console.log(`图片服务已启动: http://localhost:${PORT}`);
});


